#include "usart.h"
#include "usbd_cdc.h"
#include <stdio.h>
////////////////////////////////////////////////////////////////////////////////// 	 
//如果使用os,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//os 使用	  
#endif
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用，未经作者许可，不得用于其它任何用途
//ALIENTEK STM32F7开发板
//串口1初始化		   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2015/6/23
//版本：V1.5
//版权所有，盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.0修改说明 
////////////////////////////////////////////////////////////////////////////////// 	  
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)	

u8  STM2PC_Data_BUF[1024];	
u16 crc16_data = 0;
u8  Working_Mode = Normal_Mode;

//#if 1
////#pragma import(__use_no_semihosting)             
////标准库需要的支持函数                 
//struct __FILE 
//{ 
//	int handle; 
//}; 

//FILE __stdout;       
////定义_sys_exit()以避免使用半主机模式    
//void _sys_exit(int x) 
//{ 
//	x = x; 
//} 
//#ifdef __GNUC__
///* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
//     set to 'Yes') calls __io_putchar() */
//    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
//#else
//  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
//#endif /* __GNUC__ */
////重定义fputc函数 
//int fputc(int ch, FILE *f)
//{ 	
////	while((USART1->ISR&0X40)==0);//循环发送,直到发送完毕   
//	//USART1->TDR=(u8)ch;      
//    HAL_UART_Transmit(&UART1_Handler, (uint8_t *)ch, 1, 0xFFFF);
//	return ch;
//}
//#endif 

u16 crc16(u8 *addr, u16 num, u16 crc)
{
    u16 i;
	u16 x;
    for(x=0; x<num; x++)             
    {
        crc = crc ^ (addr[x] << 8);     /* Fetch byte from memory, XOR into CRC top byte*/
        for (i = 0; i < 8; i++)             /* Prepare to rotate 8 bits */
        {
            if (crc & 0x8000)            /* b15 is set... */
                crc = (crc << 1) ^ 0x1021;    /* rotate and XOR with polynomic */
            else                          /* b15 is clear... */
                crc <<= 1;                  /* just rotate */
        }                             /* Loop for 8 bits */
//        crc &= 0xFFFF;                  /* Ensure CRC remains 16-bit value */
    }                               /* Loop until num=0 */
    return(crc);                    /* Return updated CRC */
}


#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15，	接收完成标志
//bit14，	接收到0x0d
//bit13~0，	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	

u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler; //UART句柄

//初始化IO 串口1 
//bound:波特率
void uart1_init(u32 bound)
{	
	//UART 初始化设置
	UART1_Handler.Instance=USART1;					    //USART1
	UART1_Handler.Init.BaudRate=bound;				    //波特率
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()会使能UART1
	
	HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断：标志位UART_IT_RXNE，并且设置接收缓冲以及接收缓冲接收最大数据量
  
}

//UART底层初始化，时钟使能，引脚配置，中断配置
//此函数会被HAL_UART_Init()调用
//huart:串口句柄

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1，进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟
//        GPIO_Initure.Pin = GPIO_PIN_9|GPIO_PIN_10;
//        GPIO_Initure.Mode = GPIO_MODE_AF_PP;
//        GPIO_Initure.Pull = GPIO_NOPULL;
//        GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
//        GPIO_Initure.Alternate = GPIO_AF7_USART1;
//        HAL_GPIO_Init(GPIOA, &GPIO_Initure);
        
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_NOPULL;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_HIGH;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		
#if EN_USART1_RX
		HAL_NVIC_EnableIRQ(USART1_IRQn);				//使能USART1中断通道
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//抢占优先级3，子优先级3
#endif	
	}

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//如果是串口1
	{
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}

	}
}
 
//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ 
	u32 timeout=0;
    u32 maxDelay=0x1F;
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	
	HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数
	
	timeout=0;
    while (HAL_UART_GetState(&UART1_Handler)!=HAL_UART_STATE_READY)//等待就绪
	{
        timeout++;////超时处理
        if(timeout>maxDelay) break;		
	}
     
	timeout=0;
	while(HAL_UART_Receive_IT(&UART1_Handler,(u8 *)aRxBuffer, RXBUFFERSIZE)!=HAL_OK)//一次处理完成之后，重新开启中断并设置RxXferCount为1
	{
        timeout++; //超时处理
        if(timeout>maxDelay) break;	
	}
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
} 
#endif	

/*下面代码我们直接把中断控制逻辑写在中断服务函数内部。*/
/*

//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ 
	u8 Res;
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!=RESET))  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
        HAL_UART_Receive(&UART1_Handler,&Res,1,1000); 
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}   		 
	}
	HAL_UART_IRQHandler(&UART1_Handler);	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
} 
#endif	
*/

 void STM2PC_ERROR(USBD_HandleTypeDef *pdev,uint8_t  ep_addr,u8 State,u8 CMD,u8 ERROR_CODE,u8 Other_data)
{
//	u8 i=0;
	STM2PC_Data_BUF[0]=State;
    STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;			
	STM2PC_Data_BUF[3]=ERROR_CODE;  	
	STM2PC_Data_BUF[4]=Other_data;		
	STM2PC_Data_BUF[5]=0X00;	
	STM2PC_Data_BUF[6]=0X00;		
	STM2PC_Data_BUF[7]=0X00;	
	STM2PC_Data_BUF[8]=0X00;	
	STM2PC_Data_BUF[9]=0X00;	
	STM2PC_Data_BUF[10]=0X00;		
	STM2PC_Data_BUF[11]=0X00;		
	STM2PC_Data_BUF[12]=0X00;	  	
	STM2PC_Data_BUF[13]=0X00;		
	STM2PC_Data_BUF[14]=0X00;		
	STM2PC_Data_BUF[15]=0x00;
	STM2PC_Data_BUF[16]=0x00;
	STM2PC_Data_BUF[17]=0x00;
	STM2PC_Data_BUF[18]=0x00;
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    USBD_LL_Transmit(pdev,CDC_IN_EP,STM2PC_Data_BUF,25); 
    	
}
void STM2PC_SSD2828(USBD_HandleTypeDef *pdev,uint8_t  ep_addr,u8 table[],u8 length)
{
	u8 i=0;
	for(i=0;i<length;i++)
	{
			STM2PC_Data_BUF[i] = table[i];
	}
	crc16_data = crc16(STM2PC_Data_BUF, length, 0xFFFF);	
	STM2PC_Data_BUF[length]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[length+1]=(u8)(crc16_data&0x00ff);

	USBD_LL_Transmit(pdev,CDC_IN_EP,STM2PC_Data_BUF,length+2); 
    	
}
void STM2PC(USBD_HandleTypeDef *pdev,uint8_t  ep_addr, u8 table[],u16 length)
{
		u16 i=0;
    for(i=0;i<length;i++)
    {
        STM2PC_Data_BUF[i] = table[i];
    }
		crc16_data = crc16(STM2PC_Data_BUF, length, 0xFFFF);	
		STM2PC_Data_BUF[length]=(u8)(crc16_data>>8);			
		STM2PC_Data_BUF[length+1]=(u8)(crc16_data&0x00ff);

    USBD_LL_Transmit(pdev,CDC_IN_EP,STM2PC_Data_BUF,length+2);    	
//#ifdef debug_log_output 
//    uart_send_str(STM2PC_Data_BUF,length+2);
//#endif	
}


void STM2PC_LCDConfig(USBD_HandleTypeDef *pdev,uint8_t  ep_addr,u8 CMD,u8 table[],u8 ERROR_CODE)
{
//	u8 i=0;
	STM2PC_Data_BUF[0]=0X0A;
    STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;	
	STM2PC_Data_BUF[3]=ERROR_CODE;	
	STM2PC_Data_BUF[4]=table[33];  	
	STM2PC_Data_BUF[5]=table[32];			//HP = 33<<8 + 32
	STM2PC_Data_BUF[6]=table[40];			//HF
	STM2PC_Data_BUF[7]=table[36];			//HB
	STM2PC_Data_BUF[8]=table[44];			//HS
	STM2PC_Data_BUF[9]=table[35];			
	STM2PC_Data_BUF[10]=table[34];			//VP = 35<<8 + 34
	STM2PC_Data_BUF[11]=table[42];			//VF
	STM2PC_Data_BUF[12]=table[38];			//VB
	STM2PC_Data_BUF[13]=table[46];	  	//VS
	STM2PC_Data_BUF[14]=table[50];			//50<<8 + 49  == ????  	
	STM2PC_Data_BUF[15]=table[49];		
	STM2PC_Data_BUF[16]=table[48];			//S_D_6_8 RGB/MIPI/DP
	STM2PC_Data_BUF[17]=table[56];			//LCDConfig
	STM2PC_Data_BUF[18]=table[63];			//RGB:0X55,MIPI:0XA1,0XA2,0XA3
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    USBD_LL_Transmit(pdev,CDC_IN_EP,STM2PC_Data_BUF,25); 	
}


void STM2PC_Pattern(USBD_HandleTypeDef *pdev,uint8_t  ep_addr,u8 CMD,u8 R,u8 G,u8 B,u8 ERROR_CODE)
{
//	u8 i=0;
	STM2PC_Data_BUF[0]=0X0A;
    STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;	
	STM2PC_Data_BUF[3]=ERROR_CODE;	
	STM2PC_Data_BUF[4]=R;  	
	STM2PC_Data_BUF[5]=G;	
	STM2PC_Data_BUF[6]=B;		
	STM2PC_Data_BUF[7]=0X00;	
	STM2PC_Data_BUF[8]=0X00;	
	STM2PC_Data_BUF[9]=0X00;	
	STM2PC_Data_BUF[10]=0X00;		
	STM2PC_Data_BUF[11]=0X00;		
	STM2PC_Data_BUF[12]=0X00;	  	
	STM2PC_Data_BUF[13]=0X00;		
	STM2PC_Data_BUF[14]=0X00;		
	STM2PC_Data_BUF[15]=0x00;
	STM2PC_Data_BUF[16]=0x00;
	STM2PC_Data_BUF[17]=0x00;
	STM2PC_Data_BUF[18]=0x00;
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    USBD_LL_Transmit(pdev,CDC_IN_EP,STM2PC_Data_BUF,25); 	
}


void STM2PC_SW_Version(USBD_HandleTypeDef *pdev,uint8_t  ep_addr,u8 State,u8 CMD,u8 ERROR_CODE,u8 Version,u8 SubVersion,u8 ID)
{
	STM2PC_Data_BUF[0]=State;
  STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;			
	STM2PC_Data_BUF[3]=ERROR_CODE;  	
	STM2PC_Data_BUF[4]=Version;		
	STM2PC_Data_BUF[5]=SubVersion;	
	STM2PC_Data_BUF[6]=ID;		
	STM2PC_Data_BUF[7]=0X00;	
	STM2PC_Data_BUF[8]=0X00;	
	STM2PC_Data_BUF[9]=0X00;	
	STM2PC_Data_BUF[10]=0X00;		
	STM2PC_Data_BUF[11]=0X00;		
	STM2PC_Data_BUF[12]=0X00;	  	
	STM2PC_Data_BUF[13]=0X00;		
	STM2PC_Data_BUF[14]=0X00;		
	STM2PC_Data_BUF[15]=0x00;
	STM2PC_Data_BUF[16]=0x00;
	STM2PC_Data_BUF[17]=0x00;
	STM2PC_Data_BUF[18]=0x00;
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    USBD_LL_Transmit(pdev,CDC_IN_EP,STM2PC_Data_BUF,25);	
}

void STM2PC_FilConfig(USBD_HandleTypeDef *pdev,uint8_t  ep_addr,u8 State,u8 CMD,u8 table[],u16 num ,u8 ERROR_CODE)
{
		u16 i=0;
		STM2PC_Data_BUF[0]=State;
		STM2PC_Data_BUF[1]=CMD;	   	
		STM2PC_Data_BUF[2]=(u8)(num>>8);
		STM2PC_Data_BUF[3]=(u8)num;		
		STM2PC_Data_BUF[4]=ERROR_CODE;

		if(CMD == 0x01)
		{
				for(i=0;i<num;i++)
				STM2PC_Data_BUF[i+5]=table[i];  
		}		
		crc16_data = crc16(STM2PC_Data_BUF, num+5, 0xFFFF);	
		STM2PC_Data_BUF[num+5]=(u8)(crc16_data>>8);			
		STM2PC_Data_BUF[num+6]=(u8)(crc16_data&0x00ff);

		USBD_LL_Transmit(pdev,CDC_IN_EP,STM2PC_Data_BUF,num+7);	
}

void Mode_Display(void)
{
	if(Working_Mode == Normal_Mode)
	{
			//printf(" ???????Normal_Mode\r\n");
			delay_ms(7);
		//printf(" \r\n");
	}
			
	else
	{
			//printf(" ??????? Debug_Mode\r\n");
			delay_ms(7);
		//printf(" \r\n");
	}
}


#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
int  fputc(int ch,FILE *f)
{
	HAL_UART_Transmit(&UART1_Handler, (uint8_t *)&ch, 1, 0xFFFF);
	
	return ch;
}

/*
功能:打印上位机指令所有数值
*/
void uart_send_str(u8 table[],u16 len)
{
    uint16_t i=0;
    printf("len = %d,\r\n",len);
    while((len-i)>0)
    {
        printf(",%#hx,\r\n",(unsigned short)table[i]);
        i++;
    }
}







 




